package cn.goour.utils.http;

import cn.goour.utils.io.FileUtils;
import cn.goour.utils.io.IO;
import cn.goour.utils.tools.FileMimeType;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.cert.Certificate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;

public class Http {
	public static void main(String[] args) {
		System.out.println();
		File[] files = new File("D:\\workspace\\eclipseJeeNeonWorkspace\\yiban-app\\target\\classes\\pic").listFiles();
		Map<String, Object> mapObj = new HashMap<>();
		Map<String, File[]> mapFiles = new HashMap<>();
		mapObj.put("a", 1);
		mapObj.put("we", "sd");
		mapFiles.put("ac[]", new File[]{files[0], files[1], files[2]});
		new HttpConfig("http://114.215.91.232/lsHelper/admin/");
		new HttpConfig("http://127.0.0.1/test/server.php");
		new HttpConfig("http://www.baidu.com");
		HttpConfig config = new HttpConfig("http://goour.cn/server.php?sd=dsdsd");
		config.setHeader("cookie", "asd=2323");
		try {
			byte[] re = post(config, mapObj, mapFiles);
			System.out.println(config.getBackHeaderCookieString());
			System.out.println(new String(re, "utf-8"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static byte[] get(HttpConfig config) throws Exception {
		String url = config.getUrl();
		if (config.getData() != null && !config.getData().trim().equals("")) {
			url = String.valueOf(url) + "?" + config.getData();
		}
		HttpURLConnection conn = getHttpURLConnection(new URL(url));
		setHeader(conn, config);
		conn.setRequestMethod("GET");
		conn.setInstanceFollowRedirects(false);
		conn.setUseCaches(false);
		conn.connect();
		InputStream in = goLocation(conn, config);
		byte[] content = IO.read(in);
		in.close();
		conn.disconnect();
		return content;
	}

	public static byte[] post(HttpConfig config) throws Exception {
		HttpURLConnection conn = getHttpURLConnection(new URL(config.getUrl()));
		setHeader(conn, config);
		conn.setRequestMethod("POST");
		conn.setInstanceFollowRedirects(false);
		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setUseCaches(false);
		PrintWriter out = new PrintWriter(conn.getOutputStream());
		out.print(config.getData());
		out.flush();
		out.close();
		InputStream in = goLocation(conn, config);
		byte[] content = IO.read(in);
		in.close();
		conn.disconnect();
		return content;
	}

	public static byte[] delete(HttpConfig config) throws Exception {
		HttpURLConnection conn = getHttpURLConnection(new URL(config.getUrl()));
		setHeader(conn, config);
		conn.setRequestMethod("DELETE");
		conn.setInstanceFollowRedirects(false);
		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setUseCaches(false);
		PrintWriter out = new PrintWriter(conn.getOutputStream());
		out.print(config.getData());
		out.flush();
		out.close();
		InputStream in = goLocation(conn, config);
		byte[] content = IO.read(in);
		in.close();
		conn.disconnect();
		return content;
	}

	@Deprecated
	public static byte[] postFile(HttpConfig config, File[] files, String key) throws Exception {
		HttpURLConnection conn = getHttpURLConnection(new URL(config.getUrl()));
		String boundary = "--------" + System.currentTimeMillis();
		setHeader(conn, config);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setUseCaches(false);
		OutputStream out1 = new DataOutputStream(conn.getOutputStream());
		out1.write(("Content-Type: multipart/form-data; boundary=" + boundary + "\r\n\r\n--" + boundary + "\r\n").getBytes());
		byte[] end = ("\r\n--" + boundary + "\r\n").getBytes();
		for (int i = 0; i < files.length; i++) {
			File file = files[i];
			byte[] fileBytes = FileUtils.read(file);
			byte[] head = ("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + file.getName() + "\"\r\n" + "Content-Type: " + FileMimeType.getFileMimeType(file) + "\r\n\r\n").getBytes();
			if (i >= files.length - 1) {
				end = ("\r\n--" + boundary + "--\r\n").getBytes();
			}
			out1.write(head);
			out1.write(fileBytes);
			out1.write(end);
			out1.flush();
		}
		out1.flush();
		out1.close();
		InputStream in = goLocation(conn, config);
		byte[] content = IO.read(in);
		in.close();
		conn.disconnect();
		return content;
	}

	public static byte[] post(HttpConfig config, Map<String, Object> mapObj, Map<String, File[]> mapFiles) throws Exception {
		HttpURLConnection conn = getHttpURLConnection(new URL(config.getUrl()));
		String boundary1 = "--------" + System.currentTimeMillis();
		setHeader(conn, config);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary1);
		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setUseCaches(false);
		OutputStream out1 = new DataOutputStream(conn.getOutputStream());
		ByteArrayOutputStream bytes = new ByteArrayOutputStream();
		bytes.write(("Content-Type: multipart/form-data; boundary=" + boundary1 + "\r\n").getBytes());
		byte[] start = ("--" + boundary1).getBytes();
		byte[] brn = "\r\n".getBytes();
		if (mapObj != null) {
			for (Map.Entry<String, Object> item : mapObj.entrySet()) {
				byte[] head = ("Content-Disposition: form-data; name=\"" + item.getKey() + "\"" + "\r\n\r\n").getBytes();
				byte[] body = item.getValue().toString().getBytes();
				bytes.write(brn);
				bytes.write(start);
				bytes.write(brn);
				bytes.write(head);
				bytes.write(body);
			}
		}
		if (mapFiles != null) {
			for (Map.Entry<String, File[]> item2 : mapFiles.entrySet()) {
				String key = item2.getKey();
				File[] files = item2.getValue();
				for (File file : files) {
					byte[] body2 = FileUtils.read(file);
					byte[] head2 = ("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + file.getName() + "\"\r\n" + "Content-Type: " + FileMimeType.getFileMimeType(file) + "\r\n\r\n").getBytes();
					bytes.write(brn);
					bytes.write(start);
					bytes.write(brn);
					bytes.write(head2);
					bytes.write(body2);
				}
			}
		}
		bytes.write(brn);
		bytes.write(start);
		bytes.write("--".getBytes());
		bytes.write(brn);
		out1.write(bytes.toByteArray());
		out1.flush();
		out1.close();
		InputStream in = goLocation(conn, config);
		byte[] content = IO.read(in);
		bytes.close();
		in.close();
		conn.disconnect();
		return content;
	}

	public static void showHeaders(Map<String, List<String>> map) {
	}

	public static void showURL(URL url) {
	}

	public static HttpURLConnection getLocation(HttpConfig config) throws Exception {
		HttpURLConnection conn = getHttpURLConnection(new URL(config.getUrl()));
		setHeader(conn, config);
		conn.setInstanceFollowRedirects(false);
		conn.setUseCaches(false);
		conn.connect();
		return conn;
	}

	public static void setHeader(HttpURLConnection conn, HttpConfig config) {
		conn.setConnectTimeout(config.getConnectTimeout());
		conn.setReadTimeout(config.getReadTimeout());
		for (Map.Entry<String, String> header : config.getSendHeader().entrySet()) {
			conn.setRequestProperty(header.getKey(), header.getValue());
		}
		String cookieString = config.getHeader("cookie");
		if (cookieString == null || cookieString.trim().equals("")) {
			cookieString = "";
		}
		conn.setRequestProperty("Cookie", String.valueOf(config.getBackHeaderCookieString()) + cookieString);
	}

	public static String getAbsUrl(String absolutePath, String relativePath) {
		try {
			return new URL(new URL(absolutePath), relativePath).toString();
		} catch (MalformedURLException e) {
			return "";
		}
	}

	public static InputStream goLocation(HttpURLConnection conn, HttpConfig config) throws Exception {
		InputStream in = conn.getInputStream();
		config.setBackHeader(conn.getHeaderFields());
		int i = 0;
		while (conn.getHeaderField("Location") != null) {
			String locationUrl = getAbsUrl(config.getUrl(), conn.getHeaderField("Location"));
			in.close();
			conn.disconnect();
			config.setUrl(locationUrl);
			conn = getLocation(config);
			in = conn.getInputStream();
			config.setBackHeader(conn.getHeaderFields());
			i++;
			if (i > 15) {
				throw new IOException("重定向次数太多！");
			}
		}
		return in;
	}

	public static boolean isHttps(URL url) {
		return url.getProtocol().equals("https");
	}

	public static HttpURLConnection initHttps(URL url) throws IOException, Exception {
		HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
		Certificate[] list = conn.getServerCertificates();
		for (Certificate certificate : list) {
		}
		conn.setHostnameVerifier(new MyHostnameVerifier());
		conn.setSSLSocketFactory(MyX509TrustManager.getSocketFactory());
		return conn;
	}

	public static HttpURLConnection initHttp(URL url) throws IOException {
		return (HttpURLConnection) url.openConnection();
	}

	public static HttpURLConnection getHttpURLConnection(URL url) throws Exception {
		showURL(url);
		if (isHttps(url)) {
			return initHttps(url);
		}
		return initHttp(url);
	}
}